package de.wwi11b2.mjp.comicvineclient;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Scanner;

public class DataHelper extends SQLiteOpenHelper {

	private SQLiteDatabase database;

	private static String apiKey = "d00a9bdd98b3981013c039dd98c24610b0210651";

	public DataHelper(Context context) {
		super(context, "myComicDb.db", null, 1);
	}

	/**
	 * Searches at the ComicVine website.
	 * 
	 * @param searchText
	 * @return
	 * @throws IOException
	 * @throws ClientProtocolException
	 * @throws URISyntaxException
	 * @throws JSONException
	 */
	public static Item search(String searchText, Item.ResourceType resourceType)
			throws ClientProtocolException, IOException, URISyntaxException {

		String searchUrl = buildSearchUrl(searchText, resourceType);
		HttpClient httpclient = new DefaultHttpClient();
		HttpResponse response = httpclient.execute(new HttpGet(new URI(
				searchUrl)));
		StatusLine statusLine = response.getStatusLine();
		HttpEntity entity = response.getEntity();
		if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
			Scanner scanner = new Scanner(entity.getContent(), "UTF-8");
			scanner.useDelimiter("\n");
			String inputStreamString = scanner.next();
			scanner.close();
			try {
				JSONObject responseObject = new JSONObject(inputStreamString);
				JSONArray resultsArray = responseObject.getJSONArray("results");
				JSONObject resultObject = resultsArray.getJSONObject(0);
				String imageUrl = (String) resultObject.getJSONObject("image")
						.get("medium_url");
				InputStream inputStream = httpclient
						.execute(new HttpGet(imageUrl)).getEntity()
						.getContent();
				byte[] image = getImageData(inputStream);
				return new Item((String) resultObject.get("name"),
						(String) resultObject.get("deck"), resourceType, image);
			} catch (JSONException e) {
				e.printStackTrace();
				return null;
			}
		} else {
			// Closes the connection.
			entity.getContent().close();
			return null;
		}

	}

	/**
	 * @param inputStream
	 * @return
	 * @throws IOException
	 */
	private static byte[] getImageData(InputStream inputStream)
			throws IOException {
		byte[] image = null;
		ByteArrayOutputStream bos = new ByteArrayOutputStream();

		byte data[] = new byte[1024];
		int count;

		while ((count = inputStream.read(data)) != -1) {
			bos.write(data, 0, count);
		}

		bos.flush();
		bos.close();
		inputStream.close();

		image = bos.toByteArray();
		return image;
	}

	/**
	 * @param searchText
	 * @param resourceType
	 * @return
	 */
	private static String buildSearchUrl(String searchText,
			Item.ResourceType resourceType) {
		String searchUrl = "http://comicvine.com/api/";
		switch (resourceType) {
		case CHARACTER:
			searchUrl += "characters";
			break;
		case LOCATION:
			searchUrl += "locations";
			break;
		default:
			return null;
		}
		searchUrl += "/?filter=name:";
		searchText = searchText.trim().toLowerCase();
		searchText = MyUrlEncoder.encode(searchText);
		searchUrl += searchText;
		searchUrl += "&field_list=name,deck,image&format=json&limit=1&api_key=";
		searchUrl += apiKey;
		return searchUrl;
	}

	/**
	 * Looks for items at the database.
	 * 
	 * @param resource
	 * @return
	 */
	public ArrayList<Item> findAll(int resource) {

		database = getReadableDatabase();
		Cursor cursor = database.rawQuery(
				"SELECT * FROM item WHERE resource = " + resource + ";", null);
		ArrayList<Item> foundItems = new ArrayList<Item>();
		cursor.moveToFirst();
		for (int i = 0; i < cursor.getCount(); i++) {
			foundItems.add(new Item(cursor.getString(1), cursor.getString(2),
					Item.ResourceType.getType(resource), cursor.getBlob(4)));
			cursor.moveToNext();
		}
		database.close();
		return foundItems;

	}

	/**
	 * Saves items into the database.
	 * 
	 * @param item
	 * @return
	 */
	public boolean save(Item item) {

		database = getWritableDatabase();
		ContentValues contentValues = new ContentValues();
		contentValues.put("name", item.getName());
		contentValues.put("description", item.getDescription());
		contentValues.put("resource", item.getResource().ordinal());
		contentValues.put("image", item.getImage());
		try {
			database.insertOrThrow("item", null, contentValues);
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		}
		database.close();
		return true;

	}

	/**
	 * Deletes items at the database.
	 * 
	 * @param item
	 * @return
	 */
	public boolean delete(Item item) {
		
		database = getWritableDatabase();
		String[] whereArgs = { item.getName(),
				"" + item.getResource().ordinal() };
		int deleted = database.delete("item",
				"item.name = ? and item.resource = ?", whereArgs);
		database.close();
		if (deleted >= 1) {
			return true;
		} else {
			return false;
		}
		
	}

	@Override
	public void onCreate(SQLiteDatabase db) {

		db.execSQL("CREATE TABLE item (id INTEGER PRIMARY KEY AUTOINCREMENT, "
				+ "name TEXT NOT NULL, "
				+ "description TEXT NOT NULL, "
				+ "resource INTEGER NOT NULL CHECK (resource >= 0 AND resource <= 2) "
				+ ", image BLOB NOT NULL);");

	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int versionAlt, int versionNeu) {
		// No upgrades planned
	}

	private static class MyUrlEncoder {

		public static String encode(String url) {
			try {
				return URLEncoder.encode(url, "UTF-8");
			} catch (UnsupportedEncodingException e) {
				// ignore it
			}
			return url;
		}

	}

}
